package ga;

import ewe.ui.Control;
import ewe.ui.MessageBox;
import masterMind.GenerarCodigo;
import masterMind.Calificador;
import masterMind.Tablero;

/**
 * MasterMind, con N = 8 y L = 5.
 * @author Roberto Loaeza Valerio
 *
 */
public class MasterMind extends MasterMindOperadoresGeneticos{
	
	/**
	 * Si el codeMaker es humano y no califica bien, cheater es True en caso contrario false.
	 */
	public boolean cheater=false;
	
	

	/**
	 * Juega MasterMind con modalidades <br>
	 * codeMaker = PC      codeBraker = PC  <br>
	 * codeMaker = PC      codeBraker = Humano <br>
	 * codeMaker = Humano  codeBraker = PC <br>
	 * codeMaker = Humano  codeBraker = Humano <br>
	 * @param t Tablero donde se mostraran las jugadas/calificaciones
	 * @param codeMaker 0 = PC, 1 = Humano
	 * @param codeBraker 0 = PC, 1 = Humano
	 * @return True si se ha logrado ganar, en caso contrario False
	 */
	public boolean jugarOP(Tablero t, int codeMaker, int codeBraker ) {
		int i=0, j=0; int k =0;
		boolean win = false;
		GenerarCodigo g2;
				
		if((codeBraker==0)&&(codeMaker==0)) {
			t.addBalls(getHistoria(0), 0, 5);
			t.addMiniBalls(new int[] {  getB(getHistoria(0)), getW(getHistoria(0))}, 0);
			t.refresh();			
		}
		else {		
			nJ--;
		}			
		while((k<J)&&(i<nR)) {			
			if(j==nH) {
				hiperMutacion();
				j=0;
				i++;
			}						
			if(codeBraker==0) {
				if(fitness()) {
					if(codeMaker==0) {
						sort();					
						D(getCodigo(), 0);																
					}
					else {
						if(!codeMakerCalif(null))
							break;
					}
										
					agregarJugada(t);
					k++;
					j=0;
					i=0;
				}
				if(this.getW(this.sacarUltimaCombinacionHistoria())==(L)) {
					win = true;					
					break;
				}else {
					j++;
					sort();
					Mutar();
				}
			}
			else {
				g2 = new GenerarCodigo();			
				if( ShowMB(g2, "Nueva Combinacion", 240, 130)==MessageBox.IDCANCEL) {
					break;
				}		
				if(codeMaker==0) {
					setIndividuo(0, g2.getCodigo());
					D(getCodigo(), 0);	
				}
				else {
					if(!codeMakerCalif(g2.getCodigo()))
						break;
				}
							
				agregarJugada(t);
				k++;
				
				if(this.getW(this.sacarUltimaCombinacionHistoria())==(L)) {
					win = true;
					break;
				}
			}
					
		}
		
		if(codeMaker==1)
			cheater = isCheater();
		return win;
	}	
	
	/**
	 * Agrega la siguiente jugada al tablero
	 * @param t Tablero
	 */
	private void agregarJugada(Tablero t) {
		agregarCombinacionHistoria(getIndividuo(0));
		t.addBalls(getHistoria(nJ-1), nJ-1, 5);
		t.addMiniBalls(new int[] {  getB(getHistoria(nJ-1)), getW(getHistoria(nJ-1))}, nJ-1);
		t.refresh();
	}
	
	/**
	 * Crea una instancia para calificar un codigo
	 * @param codigo Codigo a calificar
	 * @return True si fue calificado, en caso contrario False
	 */
	private boolean codeMakerCalif(char[] codigo) {
		Calificador g3;
		if(codigo!=null)
			setIndividuo(0, codigo);
		g3 = new Calificador(getIndividuo(0));
		if(ShowMB(g3, "Calificacion", 240, 180)==MessageBox.IDCANCEL) {
			return false;
		}
		setB(0, g3.getB());
		setW(0, g3.getW());				
		return true;
	}	
	
	/**
	 * Solicita el codigo secreto y comprueba si el calificador hizo trampa
	 * @return True para trampa, en caso contrario False
	 */	
	private boolean isCheater() {
		GenerarCodigo g2= new GenerarCodigo();
		if(ShowMB(g2 , "Codigo Secreto", 240, 130)!=MessageBox.IDCANCEL) {			
			setCodigo(g2.getCodigo());
			for(int i=0; i< nJ; i++) {				
				setIndividuo(0,clone(getHistoria(i)));
				D(getCodigo(), 0);
				if((getB(getIndividuo(0))!=getB(getHistoria(i)))||(getW(getIndividuo(0))!=getW(getHistoria(i))) ) {
					return true;
				}
			}			
		}
		return false;
	}
	
	/**
	 * Test
	 * @return True si se ha logrado ganar, en caso contrario False
	 */
	public boolean jugar() {
		int i=0, j=0; int k =0;
		boolean win = false;
		
		while((k<J)&&(i<nR)) {
			if(j==nH) {
				//this.crearPoblacion(nPob);
				hiperMutacion();
				j=0;
				i++;
			}
			
			if(fitness()) {
				sort();					
				D(getCodigo(), 0);
				agregarCombinacionHistoria(getIndividuo(0));		
				k++;
				j=0;
				i=0;
			}
			if(this.getW(this.sacarUltimaCombinacionHistoria())==(L)) {
				win = true;
				break;
			}else {
				j++;
				sort();
				Mutar();
			}
		}
		return win;
	}	
	
	public MasterMind() {
		super();
	}
	/**
	 * Crea una instancia de MasterMindBase 
	 * @param np # de poblacion
	 * @param nj # maximo de jugadas
	 * @param nh # de generaciones antes de hipermutacion
	 * @param nc % de cruza
	 * @param nt % de transposicion
	 * @param nm % de mutacion circular
	 * @param nr # de hipermutaciones antes de game over
	 */
	public MasterMind(int np, int nj, int nh, int nc, int nt, int nm, int nr) {
		super(np, nj, nh, nc, nt, nm, nr);
	}
	
	/**
	 * Muestra un MessageBox con contenido ob
	 * @param ob Objeto a mostrar en el MessageBox
	 * @param titulo Titulo del MessageBox
	 * @param ancho Ancho del MessageBox
	 * @param alto Alto del MessageBox
	 * @return MBOK o MBCANCEL
	 */
	private int ShowMB(Control ob, String titulo, int ancho, int alto) {
		MessageBox mb = new MessageBox(titulo, "",MessageBox.MBOKCANCEL);        
        mb.doBeep=false; 
        mb.addLast(ob);
        mb.setPreferredSize(ancho, alto);        
        return mb.execute();
	}	
}
